package org.xiaoxin.onecoupon.distribution.mq.consumer;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.aspectj.bridge.MessageWriter;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.xiaoxin.onecoupon.distribution.common.enums.CouponTaskStatusEnum;
import org.xiaoxin.onecoupon.distribution.common.enums.CouponTemplateStatusEnum;
import org.xiaoxin.onecoupon.distribution.dao.entity.CouponTaskDO;
import org.xiaoxin.onecoupon.distribution.dao.entity.CouponTemplateDO;
import org.xiaoxin.onecoupon.distribution.dao.mapper.CouponTaskFailMapper;
import org.xiaoxin.onecoupon.distribution.dao.mapper.CouponTaskMapper;
import org.xiaoxin.onecoupon.distribution.dao.mapper.CouponTemplateMapper;
import org.xiaoxin.onecoupon.distribution.dao.mapper.UserCouponMapper;
import org.xiaoxin.onecoupon.distribution.mq.base.MessageWrapper;
import org.xiaoxin.onecoupon.distribution.mq.event.CouponTaskExecuteEvent;
import org.xiaoxin.onecoupon.distribution.mq.producer.CouponExecuteDistributionProducer;
import org.xiaoxin.onecoupon.distribution.service.handler.excel.CouponTaskExcelObject;
import org.xiaoxin.onecoupon.distribution.service.handler.excel.ReadExcelDistributionListener;
import org.xiaoxin.onecoupon.framework.idempotent.NoMQDuplicateConsume;

/**
 * 优惠券推送定时执行-真实执行消费者
 * @author xiaoxin
 * 2025/4/25
 */
@Component
@RequiredArgsConstructor
@RocketMQMessageListener(
        topic = "one-coupon_distribution-service_coupon-task-execute_topic${unique-name:}",
        consumerGroup = "one-coupon_distribution-service_coupon-task-execute_cg${unique-name:}"
)
@Slf4j(topic = "CouponTaskExecuteConsumer")
public class CouponTaskExecuteConsumer implements RocketMQListener<MessageWrapper<CouponTaskExecuteEvent>> {

   private  final CouponTaskMapper couponTaskMapper;
   private  final CouponTemplateMapper couponTemplateMapper;
   private  final StringRedisTemplate stringRedisTemplate;
   private  final UserCouponMapper userCouponMapper;
   private  final CouponTaskFailMapper couponTaskFailMapper;
   private  final CouponExecuteDistributionProducer couponExecuteDistributionProducer;
   @NoMQDuplicateConsume(
           keyPrefix = "coupon_task_execute:idempotent:",
           key = "#messageWrapper.message.couponTaskId",
           keyTimeout = 120
   )
   @Override
   public void onMessage(MessageWrapper<CouponTaskExecuteEvent> messageWrapper) {
      // 开头打印日志，平常可 Debug 看任务参数，线上可报平安（比如消息是否消费，重新投递时获取参数等）
      log.info("[消费者] 优惠券推送任务正式执行 - 执行消费逻辑，消息体：{}", JSON.toJSONString(messageWrapper));
      //判断优惠劵任务状态是否为执行中
      Long couponTaskId = messageWrapper.getMessage().getCouponTaskId();
      CouponTaskDO couponTaskDO = couponTaskMapper.selectById(couponTaskId);
      if (ObjectUtil.notEqual(couponTaskDO.getStatus(), CouponTaskStatusEnum.IN_PROGRESS.getStatus())){
         log.warn("[消费者] 优惠券推送任务正式执行 - 推送任务记录状态异常：{}，已终止推送", couponTaskDO.getStatus());
         return;
      }
      //判断分发的优惠劵是否有效
      LambdaQueryWrapper<CouponTemplateDO> queryWrapper = Wrappers.lambdaQuery(CouponTemplateDO.class)
              .eq(CouponTemplateDO::getShopNumber, couponTaskDO.getShopNumber())
              .eq(CouponTemplateDO::getId, couponTaskDO.getCouponTemplateId());
      CouponTemplateDO couponTemplateDO = couponTemplateMapper.selectOne(queryWrapper);
      if (ObjectUtil.notEqual(couponTemplateDO.getStatus(),CouponTemplateStatusEnum.ACTIVE.getStatus())){
         log.error("[消费者] 优惠券推送任务正式执行 - 优惠券ID：{}，优惠券模板状态：{}", couponTaskDO.getCouponTemplateId(), couponTemplateDO.getStatus());
         return;
      }
      //正式开始执行分发优惠劵任务
      ReadExcelDistributionListener readExcelDistributionListener = new ReadExcelDistributionListener(
         couponTaskDO,
         couponTemplateDO,
         stringRedisTemplate,
         couponTaskFailMapper,
         couponExecuteDistributionProducer
      );
      EasyExcel.read(couponTaskDO.getFileAddress(), CouponTaskExcelObject.class, readExcelDistributionListener).sheet().doRead();
   }
}
